/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * File Name          : freertos.c
  * Description        : Code for freertos applications
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2025 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "queue.h"
#include "bsp_led_driver.h"
#include "bsp_led_handler.h"
#include "usbd_cdc_if.h"
#include "usart.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define HANDLER_1_DEBUG 1


led_status_t led_on_myown(void){
	printf("led is on\n");
	return LED_OK;
}

led_status_t led_off_myown(void){
	printf("led is off \n");
	return LED_OK;
}

led_operation_t  led_operation_myown = {
	.pf_led_on = led_on_myown,
	.pf_led_off = led_off_myown
};

led_status_t pf_get_time_ms_own( uint32_t * const time_step){
	printf("get time now timezero \n");
	*time_step = 0;
	return LED_OK;
}


time_base_ms_t time_base_ms_myown = {
	.pf_get_time_ms = pf_get_time_ms_own
};


led_status_t pf_os_delay_ms_myown	( const uint32_t delay_time){
	//printf("pf_os_delay_ms now delay 1ms \n");

//	for(int i =delay_time; i >0 ; i--){
//	
//	}
	vTaskDelay(delay_time);
	printf("delay [%d]ms finished \n", delay_time);
	return LED_OK;
}




os_delay_t os_delay_myown = {
	.pf_os_delay_ms = pf_os_delay_ms_myown
};

// self-test :: driver-layer-testing
void Test_1()
{
	led_status_t ret = LED_OK;
	
	bsp_led_driver_t LED_Y,LED_B;
	ret = led_driver_inst(&LED_Y,
						  &led_operation_myown,
						  &time_base_ms_myown,
						  &os_delay_myown);
	ret = LED_Y.pf_led_controler(&LED_Y,5,4,PROPORTION_1_1);
	ret = led_driver_inst(&LED_B,
						  &led_operation_myown,
						  &time_base_ms_myown,
						  &os_delay_myown);
	ret = LED_Y.pf_led_controler(&LED_B,2,10,PROPORTION_1_1);

}


led_handler_status_t os_delay_ms_handler_1( const uint32_t delay_time){
	vTaskDelay(delay_time);
#ifdef HANDLER_1_DEBUG
		printf("os_delay_ms_handler_1\r\n");
#endif // HANDLER_1_DEBUG	
	printf("delay [%d]ms finished handler_1\n", delay_time);
	return LED_OK;
}

os_delay_t handler_1_os_delay = {
	.pf_os_delay_ms = os_delay_ms_handler_1
};

led_handler_status_t os_queue_create_handler_1( 
											 uint32_t const       item_num, 
											 uint32_t const      item_size,
											 void ** const   queue_handler)
{
#ifdef HANDLER_1_DEBUG
		printf("os_queue_create_handler_1\r\n");
#endif // HANDLER_1_DEBUG	
	QueueHandle_t temp_queue_handle = NULL;
	temp_queue_handle = xQueueCreate(item_num,item_size);
	if( NULL == temp_queue_handle )
	{
		return HANDLER_ERRORRESOURCE;
	}
	else
	{
		*queue_handler = temp_queue_handle; 
		return HANDLER_OK;
	}
}

led_handler_status_t os_queue_put_handler_1( 
												 void * const    queue_handler,
												 void * const 		      item,
												 uint32_t              timeout)
{
#ifdef HANDLER_1_DEBUG
		printf("os_queue_put_handler_1\r\n");
#endif // HANDLER_1_DEBUG	
	led_handler_status_t ret = HANDLER_OK;
	if( NULL == queue_handler ||
		NULL ==          item ||
		timeout > portMAX_DELAY )
		
	{
		return HANDLER_ERRORRESOURCE;
	}
	else
	{
		ret = xQueueSend(queue_handler, item, timeout);
		if( ret == pdFALSE )
		{
			ret = HANDLER_ERROR;
		}
		return HANDLER_OK;
	}
}


led_handler_status_t os_queue_get_handler_1( 
												 void * const    queue_handler,
												 void * const 		       msg,
												 uint32_t              timeout)
{
#ifdef HANDLER_1_DEBUG
		printf("os_queue_get_handler_1\r\n");
#endif // HANDLER_1_DEBUG	
	led_handler_status_t ret = HANDLER_OK;
	if( NULL == queue_handler ||
		NULL ==           msg ||
		timeout > portMAX_DELAY )
		
	{
		return HANDLER_ERRORRESOURCE;
	}
	else
	{
		ret = xQueueReceive(queue_handler,msg,timeout);

		if( ret == pdFALSE )
		{
			ret = HANDLER_ERROR;
		}
		return HANDLER_OK;
	}
}

led_handler_status_t os_queue_delete_1(  void * const    queue_handler)
{
#ifdef HANDLER_1_DEBUG
		printf("os_queue_delete_1\r\n");
#endif // HANDLER_1_DEBUG	
	if( NULL == queue_handler )
	{
		return HANDLER_ERRORRESOURCE;
	}
	vQueueDelete(queue_handler);
	return HANDLER_OK;
}


handler_os_queue_t handler1_os_queue = {
	.pf_os_queue_create = os_queue_create_handler_1,
	.pf_os_queue_put	=    os_queue_put_handler_1,
	.pf_os_queue_get	=    os_queue_get_handler_1,
	.pf_os_queue_delete	=         os_queue_delete_1
};


led_handler_status_t os_critical_enter_handler_1( void )
{
	//TBD:if already in critical state,return error
	vPortEnterCritical();
	return HANDLER_OK;
}
led_handler_status_t os_critical_exit_handler_1( void )
{
	//TBD:if already in critical state,return error
	vPortExitCritical();
	return HANDLER_ERROR;
}


handler_os_critical_t handler1_os_critical = {
	.pf_os_critical_enter = os_critical_enter_handler_1,
	.pf_os_critical_exit  =  os_critical_exit_handler_1
};


led_handler_status_t get_time_ms_handler1( uint32_t * const p_os_tick)
{
	if( NULL == p_os_tick)
	{
		return HANDLER_ERRORRESOURCE;
	}
	*p_os_tick = HAL_GetTick();
}

handler_time_base_ms_t handler1_time_base = {
	.pf_get_time_ms = get_time_ms_handler1

};
// self-test :: handler-layer-testing
void Test_2()
{
//******************************** Handler **********************************//
	led_handler_status_t ret = HANDLER_OK;
	
	bsp_led_handler_t handler_1;

	ret = led_handler_inst(	&handler_1,
							&handler_1_os_delay,
							&handler1_os_queue,
							&handler1_os_critical,
						    &handler1_time_base
						  );

	
//******************************** Driver  **********************************//	
	led_status_t ret1 = LED_OK;
	
	bsp_led_driver_t LED_Y,LED_B;
	ret1 = led_driver_inst(&LED_Y,
						   &led_operation_myown,
						   &time_base_ms_myown,
						   &os_delay_myown);
	
	ret1 = led_driver_inst(&LED_B,
						   &led_operation_myown,
						   &time_base_ms_myown,
						   &os_delay_myown);
						  
	ret1 = LED_Y.pf_led_controler(&LED_Y,5,30,PROPORTION_1_1);
	ret1 = LED_B.pf_led_controler(&LED_B,2,10,PROPORTION_1_1);
	
//**************************** Intergrated Test *****************************//	
	led_index_t handler1_led_index = LED_NOT_INITED;
	ret = handler_1.pf_led_register(&handler_1,
									&LED_Y,
									&handler1_led_index);

	printf("The return of  handler_1.pf_led_register is [%d] \n ",ret);
	printf("The registered led1 index is led_[%d] \n ",handler1_led_index+1);

	ret = handler_1.pf_led_register(&handler_1,
									&LED_B,
									&handler1_led_index);

	printf("The return of  handler_1.pf_led_register is [%d] \n ",ret);
	printf("The registered led2 index is led_[%d] \n ",handler1_led_index+1);




}
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */

/* USER CODE END Variables */
/* Definitions for defaultTask */
osThreadId_t defaultTaskHandle;
const osThreadAttr_t defaultTask_attributes = {
  .name = "defaultTask",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityNormal,
};

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */

/* USER CODE END FunctionPrototypes */

void StartDefaultTask(void *argument);

extern void MX_USB_DEVICE_Init(void);
void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */

/**
  * @brief  FreeRTOS initialization
  * @param  None
  * @retval None
  */
void MX_FREERTOS_Init(void) {
  /* USER CODE BEGIN Init */
  /* USER CODE END Init */

  /* USER CODE BEGIN RTOS_MUTEX */
  /* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */

  /* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */

  /* USER CODE BEGIN RTOS_QUEUES */
  /* add queues, ... */
  /* USER CODE END RTOS_QUEUES */

  /* Create the thread(s) */
  /* creation of defaultTask */
  defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);

  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */
  /* USER CODE END RTOS_THREADS */

  /* USER CODE BEGIN RTOS_EVENTS */
  /* add events, ... */
  /* USER CODE END RTOS_EVENTS */

}

/* USER CODE BEGIN Header_StartDefaultTask */
/**
  * @brief  Function implementing the defaultTask thread.
  * @param  argument: Not used
  * @retval None
  */
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument)
{
  /* init code for USB_DEVICE */
  MX_USB_DEVICE_Init();
  /* USER CODE BEGIN StartDefaultTask */
	printf("hello world 1\n");
	//Test_1();
	Test_2();
	printf("hello world 2\n");
  /* Infinite loop */
  for(;;)
  {
		//printf("hello\n");

	
	
    osDelay(1000);
  }
  /* USER CODE END StartDefaultTask */
}

/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */

/* USER CODE END Application */

